﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.Text;
using System.IO;

namespace anks.Lib.Config
{
    public class ConfigReaderIni : CustomConfigReader
    {
        public class ParseError : Exception
        {
        }

        private bool IsBlankLine(string line)
        {
            return (line == "");
        }

        private bool IsRemarkLine(string line)
        {
            return line.StartsWith(";") || line.StartsWith("#");
        }

        private bool IsGroupHeaderLine(string line, out string groupName)
        {
            if (line.StartsWith("[") && line.EndsWith("]"))
            {
                groupName = line.Substring(1, line.Length - 2);
                return true;
            }
            else
            {
                groupName = "";
                return false;
            }
        }

        private bool IsNodeLine(string line, out string nodeName, out string nodeValue)
        {
            char[] splitChars = { '=' };
            string[] parts;
            if (line.Contains("=") && ((parts = line.Split(splitChars)).Length == 2))
            {
                nodeName = parts[0];
                nodeValue = parts[1];
                return true;
            }
            else
            {
                nodeName = "";
                nodeValue = "";
                return false;
            }
        }
        
        public override Config Read(string source)
        {
            Config config = new Config();
            if (File.Exists(source))
            {
                ConfigGroup currentGroup = null;
                using (StreamReader reader = File.OpenText(source))
                {
                    string line;
                    string groupName;
                    string nodeName;
                    string nodeValue;
                    while ((line = reader.ReadLine()) != null)
                    {
                        line = line.Trim();
                        if (IsBlankLine(line) || IsRemarkLine(line))
                            continue;

                        if (IsGroupHeaderLine(line, out groupName))
                        {
                            currentGroup = config.AddGroup(groupName);
                        }
                        else
                        {
                            if (IsNodeLine(line, out nodeName, out nodeValue))
                            {
                                if (currentGroup == null)
                                    throw new ParseError();
                                currentGroup.AddNode(nodeName, nodeValue);

                            }
                            else
                                throw new ParseError();
                        }
                    }
                }
            }
            return config;
        }
    }
}
